#pragma once

#include <iostream>
#include <memory>
#include <functional>
#include <sys/wait.h>

#include "Socket.hpp"

namespace TcpServerModule
{
    using namespace SockModule;
    using namespace LogModule;

    using handler_t = std::function<void(SockPtr, InetAddr)>;
    class TcpServer
    {   
    public:
        TcpServer(int port)
        : _listensockp(std::make_unique<TcpSocket>()/*创建子类对象，并用基类指针_listensockp指向*/)
        , _isrunning(false)
        , _port(port)
        {
        }

        void InitServer(handler_t tcpHandler){
            _tcpHandler = tcpHandler;
            _listensockp->BuildTcpSocket(_port);
        }

        void Loop()
        {
            _isrunning = true;
            while(_isrunning)
            {
                // Accept
                InetAddr clientaddr;
                SockPtr sockfd = _listensockp->Accepter(&clientaddr);
                if(sockfd == nullptr) continue;

                // IO 处理
                LOG(LogLevel::DEBUG) << "get a new client, info is: "<< clientaddr.Addr();
                // sockfd->Recv();
                // sockfd->Send();
            
                pid_t id = fork();
                if(id == 0){
                    _listensockp->Close();
                    if(fork() > 0) exit(0);
                    _tcpHandler(sockfd, clientaddr);
                    exit(0);
                }    
                sockfd->Close();
                waitpid(id, nullptr, 0);

            }
            _isrunning = false;
        }

        ~TcpServer(){}

    private:
        std::unique_ptr<Socket> _listensockp;
        bool _isrunning;
        handler_t _tcpHandler; // 方法实现给上层决定
        int _port;
    };

}